#include "Learning.h"

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Learning
 *      Method:  Learning
 * Description:  Constrói um aprendizado dando seu tipo e a função de ativação
 *--------------------------------------------------------------------------------------
 */
Learning::Learning(int type, ActivationPtr activation)
{
    this->type = type;
    this->activation = activation;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Learning
 *      Method:  delta
 * Description:  Retorna a variação do peso dado a entrada e o erro de saída
 *--------------------------------------------------------------------------------------
 */
void Learning::calcLearningRate(uint i)
{
    double val = i / (double) ALPHA;
    learningRate = (MAX - MIN) * exp(-val) + MIN;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Learning
 *      Method:  delta
 * Description:  Retorna a variação do peso dado a entrada e o erro de saída
 *--------------------------------------------------------------------------------------
 */
double Learning::delta(double input, double error)
{
    double delta;

    switch(type)
    {
        // Supervisionado: dW = rate * error * input
        case SUPERVISIONED:
            delta = learningRate * error * input;
            break;

        default:
            delta = 0;
            break;
    }

    return delta;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Learning
 *      Method:  error
 * Description:  Calcula o erro na camada de saída
 *--------------------------------------------------------------------------------------
 */
double Learning::error(double expected, double output, double sum)
{
    double res = (expected - output) * activation->derivate(sum);
    return res;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Learning
 *      Method:  error
 * Description:  Calcula o erro nas camadas escondidas
 *--------------------------------------------------------------------------------------
 */
double Learning::error(vdoublePtr errors, vdoublePtr weights, double sum)
{
    double s = 0;

    for(uint k = 0; k < errors->size(); k++)
        s += errors->at(k) * weights->at(k);

    return s * activation->derivate(sum);
}
